import os
import time
import datetime

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

from xkw_UI_auto.Logs.log import get_log
from xkw_UI_auto.getcwd import get_cwd


class BasePage(object):

    def __init__(self, driver):
        self.driver = driver
        self.log = get_log(__name__)
        self.path = get_cwd()

    def refresh_page(self):
        self.driver.refresh()

    # 等待元素可见
    def wait_element_visible(self, locator, times=10, poll_frequency=0.5, doc=''):
        """
        function：等待元素可见，如果元素可见，打印出等待时长，如不可见，输入异常日志到日志文件并截图当前元素所在页面
        :param locator: 元素定位，元组形式(定位类型，元素定位表达式)
        :param times: 等待最长时间
        :param poll_frequency: 查询时间频率，默认0.5秒
        :param doc: 操作位置，如：项目名称_功能名称_操作页面
        :return: None
        """
        self.log.info("{} 等待元素 {} 可见".format(doc, locator))
        try:
            startTime = datetime.datetime.now()
            # 等待元素出现
            WebDriverWait(self.driver, times, poll_frequency).until(EC.visibility_of_element_located(locator))
            endTime = datetime.datetime.now()
            self.log.info("{} 元素 {}等待结束，等待时长为：{} 秒".format(doc, locator, (endTime - startTime).seconds))
        except:
            self.log.exception("{} 等待元素{} 可见失败".format(doc, locator))
            # 截图操作
            self.save_screen_shot(doc)
            raise

    # 等待元素存在
    def wait_element_presence(self, locator, times=10, poll_frequency=0.5, doc=''):
        self.log.info("{} 等待元素 {} 存在".format(doc, locator))
        try:
            startTime = datetime.datetime.now()
            WebDriverWait(self.driver, times, poll_frequency).until(EC.presence_of_element_located(locator))
            endTime = datetime.datetime.now()
            self.log.info("{} 元素 {}等待结束，等待时长为：{} 秒".format(doc, locator, (endTime - startTime).seconds))
            return True
        except:
            self.log.exception("{} 等待元素 {} 存在失败".format(doc, locator))
            self.save_screen_shot(doc)
            return False

    # 查找单个元素
    def get_element(self, locator, doc=''):
        self.log.info("{} 查找元素：{}".format(doc, locator))
        self.wait_element_visible(locator, doc=doc)
        try:
            return self.driver.find_element(*locator)
        except:
            self.log.exception("{} 查找元素：{} 失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 查找一组元素
    def get_elements(self, locator, doc=''):
        self.log.info("{} 查找一组元素：{}".format(doc, locator))
        time.sleep(5)
        try:
            return self.driver.find_elements(*locator)
        except:
            self.log.exception("{} 查找一组元素：{} 失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 点击元素
    def click_element(self, locator, doc=''):
        # 找元素
        ele = self.get_element(locator, doc)
        try:
            ele.click()
        except:
            self.log.exception("{0} 点击元素 {1} 失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 输入操作
    def input_text(self, locator, text, doc=''):
        # 找元素
        ele = self.get_element(locator, doc)
        ele.clear()
        try:
            ele.send_keys(text)
        except:
            self.log.exception("{} 元素 {} 输入框输入失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 获取元素文本
    def get_element_text(self, locator, doc=''):
        # 找元素
        ele = self.get_element(locator, doc)
        try:
            return ele.text
        except:
            self.log.exception("{} 获取元素 {} 文本失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 获取新页面元素文本
    def get_new_page_context(self, title, locator, doc=''):
        self.switch_new_windows_handle(doc)
        # 找元素
        ele = self.get_element(locator, doc)
        try:
            text = ele.text
            self.keep_default_windows_handle(title, doc)
            return text
        except:
            self.log.exception("{} 获取元素 {} 文本失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 获取页面URL
    def get_page_url(self, doc=''):
        try:
            return self.driver.current_url
        except:
            self.log.exception("{}获取页面标题内容失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 获取页面title
    def get_page_title(self, doc=''):
        try:
            return self.driver.title
        except:
            self.log.exception("{}获取页面url失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 获取元素属性
    def get_element_attribute(self, locator, attr, doc):
        # 找元素
        ele = self.get_element(locator, doc)
        try:
            return ele.get_attribute(attr)
        except:
            self.log.exception("{} 获取元素 {} 的属性失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # alert处理
    def alert_action(self, action='accept', doc=''):
        try:
            self.driver.switch_to.alert.accept()
        except:
            self.log.exception("切换到alert失败")
            self.save_screen_shot(doc)
            raise

    # iframe 切换
    def switch_to_iframe(self, locator, doc=''):
        self.log.info("{} iframe切换 {}".format(doc, locator))
        try:
            self.driver.switch_to.frame(locator)
        except:
            self.log.exception("切换到frame失败")
            self.save_screen_shot(doc)
            raise

    # 上传操作,input窗口
    def upload_file_isInput(self, locator, file, doc=''):
        self.log.info("{0} {1}文件上传 {2}".format(doc, locator, file))
        # 点击上传按钮
        ele = self.get_element(locator, doc=doc)
        # 输入文件地址
        try:
            ele.send_keys(file)
        except:
            self.log.exception("{} 文件地址输入失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 上传操作,非input窗口
    def upload_file_notInput(self, locator, file, doc=''):
        self.log.info("{0} {1}文件上传 {2}".format(doc, locator, file))
        # 点击上传按钮
        self.click_element(locator, doc=doc)
        time.sleep(3)
        # 输入文件地址
        try:
            exec_path = os.path.join(self.path, r'TestDatas\common\upload.exe') + ' ' + file
            self.log.info('exec_path: {}'.format(exec_path))
            os.system(exec_path)
        except:
            self.log.exception("{} 文件上传失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 滚动到元素可见
    def scroll_window_element_visible(self, locator, doc):
        # 查找元素
        ele = self.get_element(locator, doc)
        # 开始滚动元素
        self.log.info("{} 滚动元素{}至页面可见".format(doc, locator))
        try:
            self.driver.execute_script("arguments[0].scrollIntoView();", ele)
        except:
            self.log.exception("{} 滚动元素{}至页面可见失败".format(doc, locator))
            self.save_screen_shot(doc)
            raise

    # 切换到新窗口
    def switch_new_windows_handle(self, doc=''):
        self.log.info("{} 切换到窗口".format(doc))
        try:
            windows = self.driver.window_handles
            self.driver.switch_to.window(windows[-1])
        except:
            self.log.exception("{} 切换窗口失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 保留默认窗口
    def keep_default_windows_handle(self, title, doc=''):
        self.log.info("{} 保留默认窗口".format(doc))
        try:
            current_handle = self.driver.current_window_handle
            handles = self.driver.window_handles
            for handle in handles:
                self.driver.switch_to.window(handle)
                page_title = self.driver.title
                if page_title != title:
                    self.driver.close()
            # self.driver.switch_to.window(current_handle)
        except:
            self.log.exception("{} 保留窗口失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 切换到指定URL窗口
    def switch_url_windows_handle(self, url, doc=''):
        self.log.info("{} 切换到指定url{}窗口".format(doc, url))
        try:
            handles = self.driver.window_handles
            for handle in handles:
                self.driver.switch_to.window(handle)
                page_url = self.driver.current_url
                if page_url == url:
                    self.driver.switch_to.window(handle)
                    self.log.info("{} 切换到指定url{}窗口完成".format(doc, url))
        except:
            self.log.exception("{} 切换到指定url {}窗口失败".format(doc, url))
            self.save_screen_shot(doc)
            raise

    # 切换到指定标题窗口
    def switch_title_windows_handle(self, title, doc=''):
        self.log.info("{} 切换到指定标题{}窗口".format(doc, title))
        try:
            handles = self.driver.window_handles
            for handle in handles:
                self.driver.switch_to.window(handle)
                page_title = self.driver.title
                if page_title == title:
                    self.driver.switch_to.window(handle)
                    self.log.info("{} 切换到指定标题{}窗口完成".format(doc, title))
        except:
            self.log.exception("{} 切换到指定标题{}窗口失败".format(doc, title))
            self.save_screen_shot(doc)
            raise

    # 鼠标悬停
    def perform_action_chains(self, locator, doc=''):
        mouse = self.get_element(locator, doc)
        self.log.info("{} 鼠标悬停到元素{}".format(doc, locator))
        try:
            ActionChains(self.driver).move_to_element(mouse).perform()
        except:
            self.log.exception("{} 鼠标悬停失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 执行js
    def exec_js(self, js, doc=''):
        self.log.info("{} 开始执行js语句： {}".format(doc, js))
        try:
            self.driver.execute_script(js)
        except:
            self.log.exception("{} js 执行失败".format(doc))
            self.save_screen_shot(doc)
            raise

    # 截图功能
    def save_screen_shot(self, fileName):
        self.log.info("开始执行截图")
        # 图片名称：项目名称_功能名称_操作页面_时间.png
        file_name = self.path + '/TestResults/images/' + fileName + time.strftime('_%Y_%m_%d_%H_%M_%S',
                                                                                  time.localtime(time.time())) + '.png'
        try:
            self.driver.save_screenshot(file_name)
            self.log.info('截图成功，截图存放在：{}'.format(file_name))
        except:
            self.log.exception('截图失败！')
            raise
